package com.pomelo.tiku.http;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;

import com.blankj.utilcode.util.LogUtils;
import com.pomelo.tiku.beans.ResponseData;
import com.pomelo.tiku.constants.SharePreferenceConstants;
import com.pomelo.tiku.interfaces.IHttpCallBack;
import com.pomelo.tiku.managers.SharedPreferenceManager;
import com.pomelo.tiku.managers.ThreadPoolManager;
import com.pomelo.tiku.utils.GsonUtil;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * @author liuxiangwang
 * @date 2022/05/05.
 */
public class OkHttpProcessor {
    private static final String TAG = OkHttpProcessor.class.getName();
    private Context mContext;
    private static OkHttpProcessor mOkHttpProcessor;
    private OkHttpClient mClient;
    private Handler mHandler;
    private static final int CONNECT_TIME_OUT = 6000;
    private static final int READ_TIME_OUT = 6000;
    private static final int WRITE_TIME_OUT = 6000;

    private OkHttpProcessor(Context context) {
        this.mContext = context;
        mHandler = new Handler(Looper.getMainLooper());
        mClient = new OkHttpClient.Builder()
                .connectTimeout(CONNECT_TIME_OUT, TimeUnit.SECONDS)      //设置连接超时
                .readTimeout(READ_TIME_OUT, TimeUnit.SECONDS)         //设置读超时
                .writeTimeout(WRITE_TIME_OUT, TimeUnit.SECONDS)        //设置写超时
                .retryOnConnectionFailure(true)            //是否自动重连
                .build();
    }

    public static OkHttpProcessor getInstance(Context context) {
        if(mOkHttpProcessor == null) {
            synchronized (OkHttpProcessor.class) {
                if(mOkHttpProcessor == null) {
                    mOkHttpProcessor = new OkHttpProcessor(context);
                }
            }

        }
        return mOkHttpProcessor;
    }

    /**
     * post请求
     * @isFormBody 是否表单格式提交
     * @param url
     * @param header
     * @param data
     * @param callBack
     */
    public void postRequest(String url, HashMap<String,String> header,HashMap<String,String> data,Boolean isFormBody, IHttpCallBack callBack) {
        RequestBody requestBody = null;
        if(isFormBody) { //表单格式提交
            FormBody.Builder builder = new FormBody.Builder();
            for(String key: data.keySet()) {
                builder.add(key,data.get(key));
            }
            requestBody = builder.build();
        } else { //json格式提交
            String jsonString = GsonUtil.parseMapToJson(data);
            LogUtils.e(TAG,jsonString);
            if(jsonString == null) {
                return;
            }
            requestBody = RequestBody.create(MediaType.parse("application/json,charset=utf-8"),jsonString);
        }
        if(requestBody == null || callBack == null) {
            LogUtils.e(TAG,"requestBody or callBack is null");
            return;
        }
        LogUtils.e(TAG,"url------->" + url);
        Request postRequest;
        String token = SharedPreferenceManager.getInstance(mContext).get(SharePreferenceConstants.Companion.getKEY_TOKEN(), "").toString();
        if(url.contains("/api/user/registry")) {
            postRequest = new Request.Builder()
                    .url(url)
                    .post(requestBody)
                    .build();
        } else {
            postRequest = new Request.Builder()
                    .url(url)
                    .addHeader("token", token)
                    .post(requestBody)
                    .build();
        }

        if (mClient == null) {
            LogUtils.e(TAG,"OkHttpClient is null");
            return;
        }

        Call call = mClient.newCall(postRequest);
        callBack.onStart();
        ThreadPoolManager.getInstance().createThreadPool().execute(() -> call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                LogUtils.e(TAG,e.getMessage());
                mHandler.postDelayed(() -> {
                    callBack.onHttpFailed(e.getMessage());
                },1000);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                int code = response.code();
                if(code == 200 && response.isSuccessful()) {
                    String body = response.body().string();
                    LogUtils.e(TAG,body);
                    ResponseData data = GsonUtil.parseJsonToBean(body,ResponseData.class);
                    if(data != null) {
                        if(data.getCode() == 200) {
                            mHandler.postDelayed(() -> {
                                callBack.onSuccess(data);
                            },1000);
                        } else {
                            mHandler.postDelayed(() -> {
                                callBack.onFailed(data.getCode(),data.getMsg());
                            },1000);

                        }

                    }else {
                        LogUtils.e(TAG,"Data is null");
                        callBack.onFailed(-1,"服务器返回数据格式有误");
                        mHandler.postDelayed(() -> {
                            callBack.onFailed(-1,"服务器返回数据格式有误");
                        },1000);
                    }
                } else {
                    mHandler.postDelayed(() -> {
                        callBack.onFailed(code, response.message());
                    },1000);
                }
            }
        }));

    }

    /**
     * get请求
     * @isFormBody 是否表单格式提交
     * @param url
     * @param header
     * @param data
     * @param callBack
     */
    public void getRequest(String url, HashMap<String,String> header,HashMap<String,String> data, IHttpCallBack callBack) {
        StringBuilder urlBuilder = new StringBuilder();
        if(data == null) {
            LogUtils.e(TAG,"参数不能为空");
            return;
        }
        urlBuilder.append(url)
                .append("?");
        for(Map.Entry < String, String > entry: data.entrySet()) {
            urlBuilder.append(entry.getKey())
                    .append("=")
                    .append(entry.getValue())
                    .append("&");
        }
        String tempUrl = urlBuilder.toString();
        String finalUrl = "";
        if(tempUrl.contains("?")) {
            finalUrl = tempUrl.substring(0,tempUrl.length()-1);
        } else {
            finalUrl = url;
        }

        LogUtils.e(TAG,"url------->" + finalUrl);
        Request getRequest = new Request.Builder()
                .url(finalUrl)
                .get()
                .build();
        if (mClient == null || callBack == null) {
            LogUtils.e(TAG,"OkHttpClient or callBack is null");
            return;
        }
        Call call = mClient.newCall(getRequest);
        callBack.onStart();
        ThreadPoolManager.getInstance().createThreadPool().execute(() -> call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                LogUtils.e(TAG,e.getMessage());
                mHandler.postDelayed(() -> {
                    callBack.onHttpFailed(e.getMessage());
                },1000);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                int code = response.code();
                LogUtils.e(TAG,response.message());
                if(code == 200 && response.isSuccessful()) {
                    String body = response.body().string();
                    LogUtils.e(TAG,body);
                    ResponseData data = GsonUtil.parseJsonToBean(body,ResponseData.class);
                    if(data != null) {
                        if(data.getCode() == 200) {
                            mHandler.postDelayed(() -> {
                                callBack.onSuccess(data);
                            },1000);
                        } else {

                            mHandler.postDelayed(() -> {
                                callBack.onFailed(data.getCode(),data.getMsg());
                            },1000);
                        }
                    } else {
                        LogUtils.e(TAG,"Data is null");

                        mHandler.postDelayed(() -> {
                            callBack.onFailed(-1,"服务器返回数据格式有误");
                        },1000);
                    }
                } else {
                    mHandler.postDelayed(() -> {
                        callBack.onFailed(code, response.message());
                    },1000);
                }
            }
        }));
    }
}
